package com.architexa.collab.ui;

import java.util.HashMap;
import java.util.Map;

import org.apache.log4j.Logger;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jface.preference.PreferencePage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPreferencePage;

import com.architexa.rse.BuildSettings;
import com.architexa.rse.PreferenceUtils;


// The build preference page tree for packages is also available on the properties page 
// of each project and is generated by (TabbedFieldEditorOverlayPage)
public class BuildPreferencePage extends PreferencePage implements IWorkbenchPreferencePage{
	static final Logger logger = Activator.getLogger(BuildPreferencePage.class);
	Tree projPackgTree;
	Map<String, IJavaProject> projectNameToResMap = new HashMap<String, IJavaProject>();
	TabFolder tabFolder;
	TabItem buildPreferenceItem;
	TabItem scheduledBuildItem;

	
	private Combo timeDropDown;
    private Combo AMPMDropDown;
    private Button daily;
    private Button onRequest;
	private Button instantly;
	private Button silently;
	//private static String LIBRARIES = "libraries"; 
	
	public BuildPreferencePage() {
		super();
		setPreferenceStore(Activator.getDefault().getPreferenceStore());
		
	}
	
	@Override
	protected Control createContents(Composite parent) {
		tabFolder = new TabFolder(parent, SWT.TOP);
		
		buildPreferenceItem = new TabItem(tabFolder, SWT.NONE);
		buildPreferenceItem.setText("Build Filters");
		Control buildContents = createBuildPrefContents(tabFolder);
		buildPreferenceItem.setControl(buildContents);
		
		scheduledBuildItem = new TabItem(tabFolder, SWT.NONE);
		scheduledBuildItem.setText("Build Schedule");
		Control buildSchedule = createBuildScheduleContents(tabFolder);
		scheduledBuildItem.setControl(buildSchedule);
		tabFolder.pack();
		return tabFolder;
	}

	public void init(IWorkbench workbench) {}
	
	@Override
	public boolean performOk() {
		PreferenceUtils.setProjFilters(projPackgTree);
		PreferenceUtils.setLibraryFilters(projPackgTree, projectNameToResMap);
		setBuildSchedule();
		return super.performOk();
	}
	
	private void setBuildSchedule() {
		if (daily.getSelection())
			BuildSettings.setBuildSchedule(BuildSettings.BUILD_DAILY);
		else if (onRequest.getSelection())
			BuildSettings.setBuildSchedule(BuildSettings.BUILD_REQUEST);
		else  if (silently.getSelection())
			BuildSettings.setBuildSchedule(BuildSettings.BUILD_SILENTLY);
		else
			BuildSettings.setBuildSchedule(BuildSettings.BUILD_INSTANTLY);
		BuildSettings.setBuildTime(getBuildTimeFromDialog());
	}
	
	private String getBuildTimeFromDialog() {
		int retVal = 0;
		if (timeDropDown.isEnabled() && AMPMDropDown.isEnabled()) {
			retVal = Integer.parseInt(timeDropDown.getText().substring(0,timeDropDown.getText().indexOf(":")));
			if (AMPMDropDown.getSelectionIndex() == 1) 
				retVal +=12;
		}
		return Integer.toString(retVal);
        
	}

	@Override
	protected void performDefaults() {
		
		if(tabFolder.getSelection().length==0) {
			logger.error("Unable to restore defaults on collab " +
			"preference page because no tab selected.");
			return;
		}
		
		TabItem selectedTab = tabFolder.getSelection()[0];
		if (buildPreferenceItem.equals(selectedTab)) {
			PreferenceUtils.selectOrDeselectAllChildren(projPackgTree.getItems(), false);
			PreferenceUtils.selectOrDeselectAllChildren(projPackgTree.getItems(), true);
			BuildSettings.setDefaultStoredUnselectedProjPackgMap();
		} else if (scheduledBuildItem.equals(selectedTab)) {
			timeDropDown.select(1);
			AMPMDropDown.select(0);
			instantly.setSelection(true);
		}
		
		super.performDefaults();
	}

	private Control createBuildPrefContents(TabFolder tabFolder) {
		Composite container = new Composite(tabFolder,SWT.NONE);
		GridLayout layout = new GridLayout(2, false);
		layout.marginHeight=0;
		container.setLayout(layout);
		GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
		data.heightHint=350;
		container.setLayoutData(data);
		
		Label desc = new Label(container, SWT.NONE);
		desc.setText("\nSelect the packages below to include in the Architexa build. " +
		"\nWe recommend you remove non-relevant packages to make the build faster.\n");
		desc.setLayoutData(new GridData(SWT.LEFT, SWT.NONE, false, false, 2, 1));
		
		addProjectSelectionArea(container);
		return container;
	}
	
	private Control createBuildScheduleContents(TabFolder tabFolder) {
		Composite container = new Composite(tabFolder,SWT.NONE);
		GridLayout layout = new GridLayout(1, false);
		layout.marginHeight=0;
		container.setLayout(layout);
		GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
		data.heightHint=350;
		container.setLayoutData(data);
		
		Label desc = new Label(container, SWT.NONE);
		desc.setText("\nSelect how often Architexa updates your indexes.\n");
		desc.setLayoutData(new GridData(SWT.LEFT, SWT.NONE, false, false, 2, 1));
		
		Group g = new Group(container, SWT.SHADOW_ETCHED_IN);
		g.setText("Schedule - Update :");
		GridLayout gl = new GridLayout();
		gl.marginLeft =10;
		g.setLayout(gl);
		addScheduleSelectionArea(g);
		return container;
	}

	private void addScheduleSelectionArea(Composite container) {
		Composite fullTabArea = new Composite(container, SWT.NONE);
		GridLayout containerLayout = new GridLayout();
		fullTabArea.setLayout(containerLayout);
		
		String schedule = BuildSettings.getBuildSchedule();
		if (schedule==null || schedule.equals(""))
			BuildSettings.setBuildSchedule(BuildSettings.DEFAULT_BUILD_SCHEDULE);
		schedule = BuildSettings.getBuildSchedule();
		
		instantly = new Button(fullTabArea, SWT.RADIO | SWT.LEFT);
		instantly.setText("Immediately as a change is made");
		instantly.setSelection(schedule.equals(BuildSettings.BUILD_INSTANTLY));
		
		silently = new Button(fullTabArea, SWT.RADIO | SWT.LEFT);
		silently.setText("Silently using minimal resources");
		silently.setSelection(schedule.equals(BuildSettings.BUILD_SILENTLY));
		
		daily = new Button(fullTabArea, SWT.RADIO | SWT.LEFT);
		daily.setText("Once a Day");
		daily.setSelection(schedule.equals(BuildSettings.BUILD_DAILY));
		
		Composite dailyArea = new Composite(fullTabArea, SWT.NONE);
		GridLayout dailyLayout = new GridLayout(2, false);
		dailyArea.setLayout(dailyLayout);
		
        timeDropDown = new Combo(dailyArea, SWT.DROP_DOWN|SWT.READ_ONLY| SWT.LEFT);
        timeDropDown.setLayoutData(new GridData());
        timeDropDown.add("1:00");
        timeDropDown.add("2:00");
        timeDropDown.add("3:00");
        timeDropDown.add("4:00");
        timeDropDown.add("5:00");
        timeDropDown.add("6:00");
        timeDropDown.add("7:00");
        timeDropDown.add("8:00");
        timeDropDown.add("9:00");
        timeDropDown.add("10:00");
        timeDropDown.add("11:00");
        timeDropDown.add("12:00");
		
        AMPMDropDown = new Combo(dailyArea, SWT.DROP_DOWN|SWT.READ_ONLY| SWT.LEFT);
        AMPMDropDown.setLayoutData(new GridData());
        AMPMDropDown.add("AM");
        AMPMDropDown.add("PM");
        AMPMDropDown.select(0);
        timeDropDown.select(1);
        if (!BuildSettings.getBuildDailyTime().equals("")) {
	        int savedTime = Integer.parseInt(BuildSettings.getBuildDailyTime());
	        if (savedTime <13) {
	        	timeDropDown.select(savedTime-1);
	        	AMPMDropDown.select(0);
	        }
	        else {
	         	timeDropDown.select(savedTime-13);
	         	AMPMDropDown.select(1);
	        }
        }
		
		onRequest = new Button(fullTabArea, SWT.RADIO);
		onRequest.setText("On my request");
		onRequest.setSelection(schedule.equals(BuildSettings.BUILD_REQUEST));
		timeDropDown.setEnabled(false);
		AMPMDropDown.setEnabled(false);
		if (daily.getSelection()) {
			timeDropDown.setEnabled(true);
			AMPMDropDown.setEnabled(true);
		}
		fullTabArea.pack();
		fullTabArea.update();
		
		daily.addSelectionListener(new SelectionListener() {
			public void widgetSelected(SelectionEvent e) {
				if (daily.getSelection()) {
					timeDropDown.setEnabled(true);
					AMPMDropDown.setEnabled(true);
				} else {
					timeDropDown.setEnabled(false);
					AMPMDropDown.setEnabled(false);
				}
			}
			public void widgetDefaultSelected(SelectionEvent e) {
			}
		});
	}

	private void addProjectSelectionArea(Composite container) {
		projPackgTree = PreferenceUtils.addAndReturnProjPackgTree(container, projectNameToResMap);
		PreferenceUtils.addSelectButtons(container, projPackgTree);
	}

	
//	private void setLibraryFilters() {
//		try {
//			for (TreeItem projectItem : projPackgTree.getItems()) {
//				IJavaProject project = projectNameToResMap.get(projectItem.getText());
//				if (project == null) {
//					logger.error("Atxa: Could not find project to save preferences: " + projectItem.getText());
//					continue;
//				}
//				
//				for (TreeItem child : projectItem.getItems()) {
//					if (!child.getText().equalsIgnoreCase(LIBRARIES)) continue;
//					
//					URL[] classPathURLArray = UIUtils.getProjectClasspath(project);
//					List<URL> classPathURLs = new ArrayList<URL>();
//					for (TreeItem libs : child.getItems()) {
//						String libName = libs.getText();
//						for (URL url : classPathURLArray) {
//							String urlStr = url.toString();
//							
//							if (libName.equalsIgnoreCase(urlStr.substring(urlStr.lastIndexOf("/") + 1))) {
//								project.getResource().setPersistentProperty(new QualifiedName(PreferenceUtils.pageId, libName), getBooleanString(libs.getChecked()));
//								if (libs.getChecked())
//									classPathURLs.add(url);
//							} 
//						}
//					}
//					
//					IProject proj = project.getResource().getProject();
//					ClassExtensionBuilder.setPersistentProperty(proj, classPathURLs);
//						
//				}
//			}
//		} catch (Exception e) {
//			logger.error("Error writing persistent properties.\n");
//			e.printStackTrace();
//		}
//	}
//	
//	private String getBooleanString(Boolean bool) {
//		if (bool) return "true";
//		return "false";
//	}
//	
//	
//	private void addChildrenToMap (TreeItem[] treeItems, List<TreeItem> unchkdList) {
//		for (TreeItem childItem : treeItems) {
//			if (childItem.getText().equalsIgnoreCase(LIBRARIES)) continue;
//			if (!childItem.getChecked())
//				unchkdList.add(childItem);
//			addChildrenToMap(childItem.getItems(), unchkdList);
//		}
//	}
//	
//	private Map<TreeItem, List<TreeItem>> getUnselectedProjectsMap () {
//		List<TreeItem> unchkdList;
//		Map<TreeItem, List<TreeItem>> projToUnchkdPackgMap = new HashMap<TreeItem, List<TreeItem>>();
//		for (TreeItem item : projPackgTree.getItems()) {
//			unchkdList = new ArrayList<TreeItem>();
//			if (!item.getChecked() && !item.getGrayed()) {
//				projToUnchkdPackgMap.put(item, unchkdList);
//				continue;
//			}
//
//			addChildrenToMap(item.getItems(), unchkdList);
//			
//			if (unchkdList.isEmpty()) continue;
//			projToUnchkdPackgMap.put(item, unchkdList);
//		}
//		return projToUnchkdPackgMap;
//	}

//	public static ISharedImages isi = JavaUI.getSharedImages();
//
//	private Tree addAndReturnProjPackgTree(Composite container) {
//		projPackgTree = new Tree(container, SWT.BORDER | SWT.CHECK);
//		GridData treeData = new GridData(SWT.FILL, SWT.FILL, true, true);
//		treeData.heightHint = 350;
//		treeData.widthHint = 250;
//		projPackgTree.setLayoutData(treeData);
//		IWorkspaceRoot root = AtxaIntroPlugin.getWorkspace().getRoot();
//
//		try {
//			IJavaProject[] javaProjects = JavaCore.create(root).getJavaProjects();
//			List<IJavaProject> projList = new ArrayList<IJavaProject>(Arrays.asList(javaProjects));
//			Collections.sort(projList, new Comparator<IJavaProject>() {
//				public int compare(IJavaProject p1, IJavaProject p2) {
//					return p1.getElementName().compareToIgnoreCase(p2.getElementName());
//				}
//			});
//			for (IJavaProject project : projList) {
//				projectNameToResMap.put(project.getElementName(), project);
//				TreeItem projItem = new TreeItem(projPackgTree, SWT.NONE);
//				projItem.setText(project.getElementName());
//				projItem.setChecked(true);
//				projItem.setImage(isi.getImage(ISharedImages.IMG_OBJS_PACKFRAG_ROOT));
//				Map<IJavaElement, TreeItem> srcRootFoldersToTreeItemMap = new HashMap<IJavaElement, TreeItem>();
//				
//				List<IPackageFragment> packageList = Arrays.asList(project.getPackageFragments());
//				Collections.sort(packageList, new Comparator<IPackageFragment>() {
//					public int compare(IPackageFragment o1, IPackageFragment o2) {
//						return o1.getParent().getElementName().compareToIgnoreCase(o2.getParent().getElementName());
//					}
//				});
//				
//				// Libraries
//				addLibrariesToTree(project, projItem);
//				
//				for (IPackageFragment pckg : packageList) {
//					IJavaElement parentFolderElem = pckg.getParent();
//					if (!pckg.containsJavaResources() || 
//							parentFolderElem instanceof JarPackageFragmentRoot)	
//						continue;
//					
//					TreeItem srcFolderTreeItem;
//					if (srcRootFoldersToTreeItemMap.containsKey(parentFolderElem)) {
//						srcFolderTreeItem = srcRootFoldersToTreeItemMap.get(parentFolderElem);
//					} else {
//						srcFolderTreeItem = new TreeItem(projItem, SWT.NONE);
//						if (parentFolderElem.getElementName().equals(""))
//							srcFolderTreeItem.setText("(default)");
//						else
//							srcFolderTreeItem.setText(parentFolderElem.getElementName());
//						srcFolderTreeItem.setChecked(true);
//						srcFolderTreeItem.setImage(isi.getImage(ISharedImages.IMG_OBJS_PACKFRAG_ROOT));
//						srcRootFoldersToTreeItemMap.put(parentFolderElem, srcFolderTreeItem);
//					}
//					
//					TreeItem pckgItem = new TreeItem(srcFolderTreeItem, SWT.NONE);
//					if (pckg.getElementName().equals(""))
//						pckgItem.setText("(default)");
//					else pckgItem.setText(pckg.getElementName());
//					pckgItem.setChecked(true);
//					pckgItem.setImage(isi.getImage(ISharedImages.IMG_OBJS_PACKAGE));
//				}
//			}
//		} catch (JavaModelException e) {
//			e.printStackTrace();
//		}
//
//		setUpTreeFromPreferences(projPackgTree);
//		addSelectionListenerToTree(projPackgTree);
//		projPackgTree.pack();
//		projPackgTree.update();
//		return projPackgTree;
//	}
//	
//	
//	private void addLibrariesToTree(IJavaProject project, TreeItem projItem) {
//		try {
//			
//			TreeItem libFolderTreeItem = new TreeItem(projItem, SWT.NONE);
//			libFolderTreeItem.setText(LIBRARIES);
//			libFolderTreeItem.setImage(isi.getImage(ISharedImages.IMG_OBJS_LIBRARY));
//			
//			List<IPackageFragmentRoot> rootList = Arrays.asList(project.getPackageFragmentRoots());
//		
//			Collections.sort(rootList, new Comparator<IPackageFragmentRoot>() {
//				public int compare(IPackageFragmentRoot o1, IPackageFragmentRoot o2) {
//					return o1.getElementName().compareToIgnoreCase(o2.getParent().getElementName());
//				}
//			});
//			List<IJavaElement> libItemList = new ArrayList<IJavaElement>();
//			for (IPackageFragmentRoot lib : rootList) {
//				if (lib instanceof JarPackageFragmentRoot) {
//					String prop = project.getResource().getPersistentProperty(new QualifiedName(PreferenceUtils.pageId, lib.getElementName()));
//					if (libItemList.contains(lib)) continue;
//					libItemList.add(lib);
//					TreeItem item = new TreeItem(libFolderTreeItem, SWT.NONE);
//					item.setText(lib.getElementName());
//					item.setImage(isi.getImage(ISharedImages.IMG_OBJS_JAR));
//					if (prop!= null && prop.equalsIgnoreCase("true")) {
//						item.setChecked(true);
//						libFolderTreeItem.setChecked(true);
//					}
//					continue;
//				}
//			}
//		} catch (JavaModelException e) {
//			e.printStackTrace();
//		} catch (CoreException e) {
//			e.printStackTrace();
//		}
//	}
//
//	@SuppressWarnings("unchecked")
//	private void setUpTreeFromPreferences(Tree tree) {
//		// Setting up the menu from the preference
//		Map storedUnselectedPrjList = BuildSettings.getStoredUnselectedProjPackgMap();
//		if (storedUnselectedPrjList == null) return;
//		for (TreeItem item : tree.getItems()) {
//			// If Parent is unchecked uncheck all children
//			List<String> list = (List<String>) storedUnselectedPrjList.get(item.getText());
//			// All packages checked
//			if (list == null) continue;
//			
//			uncheckFromPref(list, item);
//		}
//	}
//	
//	private void uncheckFromPref(List<String> list, TreeItem treeItem) {
//		TreeItem[] treeItems = treeItem.getItems();
//		int size = treeItems.length;
////		if (size <= 0) return;
//		if (list.isEmpty()) { // Project Unchecked
//			treeItem.setChecked(false);
//			selectOrDeselectAllChildren(treeItems, false);
//			return;	
//		}
//		
//		for (TreeItem childItem : treeItems) {
//			if (list.contains(childItem.getText())) {
//				childItem.setChecked(false);
//				size--;
//			}
//			uncheckFromPref(list, childItem);
//			if (size == 0) treeItem.setChecked(false);
//		}
//	}
//
//	private void addSelectionListenerToTree(final Tree tree) {
//		tree.addSelectionListener(new SelectionListener() {
//			int count =1;
//			public void widgetSelected(SelectionEvent e) {
//				// This hack prevents the listener from firing when the
//				// preference tree area is 'selected' for the first time.
//				// Otherwise all the children of the first node will be checked
//				// even if the preferences are different...
//				try {
//					TreeItem item = (TreeItem) e.item;
//					if (item.equals(tree.getItems()[0]) && count == 1) {
//						count++;
//						return;
//					}
//					boolean isSelected = item.getChecked();
//					selectOrDeselectAllAncestors(item, isSelected);
//					selectOrDeselectAllChildren(item.getItems(), isSelected);
//				} catch (Throwable t) {
//					logger.error("Error in preference page for Item: " + ((TreeItem) e.item) + "\nTree Items: " + tree.getItems(), t);
//				}
//			}
//
//			public void widgetDefaultSelected(SelectionEvent e) {
//				e.getSource();
//			}
//		});
//	}
//
//	protected void selectOrDeselectAllAncestors(TreeItem item,
//			boolean isSelected) {
//		while (item.getParentItem() != null) {
//			item.getParentItem().setChecked(isSelected);
//			if (!isSelected) {
//				for (TreeItem childItem : item.getParentItem().getItems()) {
//					if (childItem.getChecked()) {
//						item.getParentItem().setChecked(true);
//						break;
//					}
//				}
//			}
//			item = item.getParentItem();
//		}
//	}
//	
//	private void selectOrDeselectAllChildren(TreeItem[] treeItems, boolean select) {
//		for(TreeItem item : treeItems) {
//			if (select && item.getText().equals(LIBRARIES)) continue;
//			selectOrDeselectAllChildren(item.getItems(), select);
//			item.setChecked(select);
//		}
//	}
	
//	public void addSelectButtons(Composite container, final Tree tree) {	
//		
//		Composite buttonColumn = new Composite(container, SWT.NONE);
//		GridLayout buttonColumnLayout = new GridLayout(1, true);
//		buttonColumn.setLayout(buttonColumnLayout);
//		buttonColumn.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, true));	
//		
//		Button selectAll = new Button(buttonColumn, SWT.PUSH);
//		selectAll.setText("Select All");
//		selectAll.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
//		selectAll.addListener(SWT.Selection, new Listener() {
//			public void handleEvent(Event event) {
//				PreferenceUtils.selectOrDeselectAllChildren(tree.getItems(), true);
//			}
//		});
//
//		Button deselectAll = new Button(buttonColumn, SWT.PUSH);
//		deselectAll.setText("Deselect All");
//		deselectAll.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
//		deselectAll.addListener(SWT.Selection, new Listener() {
//			public void handleEvent(Event e) {
//				PreferenceUtils.selectOrDeselectAllChildren(tree.getItems(), false);
//			}
//			
//		});
//		
//		buttonColumn.pack();
//		buttonColumn.update();
//	}

}
